#include "PlayState.h"
#include "Game.h"
#include "EventPoller.h"

#include <SDL_OpenGL.h>
#include <GL/glut.h>

#define FLOOR 0

PlayState::PlayState()
{
	glEnable(GL_LIGHTING);
	glEnable(GL_LIGHT0);
	glEnable(GL_DEPTH_TEST);
	glEnable(GL_COLOR_MATERIAL);

	TheCar::Instance()->Load("BodyTextured.obj", "HiluxWheelLeft.obj");

	TheCar::Instance()->SetPos(Vec3f(0,0,0));
	TheEventPoller::Instance()->AddHandler(TheCar::Instance());
	TheEventPoller::Instance()->AddHandler(TheCamera::Instance());
	TheCamera::Instance()->Prepare();
	m_texture.Load("Road.jpg");		//load the texture for the road
}
void PlayState::CleanUp()
{
	m_texture.Unload();
	TheCar::Instance()->Unload();
}

void PlayState::Update()
{
	CheckForErrors();
	TheCar::Instance()->Update();
	TheCamera::Instance()->Update();
}
void PlayState::CheckForErrors()
{
	char* c = SDL_GetError();
	int x = glGetError();

	if(x == GL_INVALID_ENUM || x == GL_INVALID_VALUE || x == GL_INVALID_OPERATION ||
	   x == GL_STACK_OVERFLOW || x == GL_STACK_UNDERFLOW || x == GL_OUT_OF_MEMORY )
	{
		//If this throws, ERROR
		assert(0);
	}

}
void PlayState::Draw()
{
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();

	glClearColor(0.0, 0.0, 0.0, 0);

	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	static int i = 0;
	i += 2.0f;

	gluPerspective(45.0 , 1.5, 1.0, 1000.0);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	TheCamera::Instance()->Update();

	glPushMatrix();						//push the matrix so we can start playing around with the surface within a push / pop
	
	
	//this moves the floor up onto the level of the ground
	glTranslatef(0,-1.1f ,0);
	m_texture.DrawTexQuad();			//draw the quad with the texture on it

	glPopMatrix();

	TheCar::Instance()->Draw();			//now draw the car 

	PrintText(0,0, "o"); //hack hack hack first text always invisible so put this in to fix that...need to come back and fix
	PrintText(50, 550, "debug info");
	PrintText(50, 650, "Car pos(x) : ");
	PrintText(200, 650, GetPosX());
	PrintText(50, 675, "Car pos(y) : ");
	PrintText(200, 675, GetPosY());
	PrintText(50, 700, "Car pos(z) : ");
	PrintText(200, 700, GetPosZ());

	//stats for speed
	PrintText(300, 650, "Car velocity(x) : ");
	PrintText(500, 650, GetVelX());
	PrintText(300, 675, "Car velocity(y) : ");
	PrintText(500, 675, GetVelY());	
	PrintText(300, 700, "Car velocity(z) : ");
	PrintText(500, 700, GetVelZ());
	//stats for camera
	PrintText(600, 650, "Cam Pos(x) : ");
	PrintText(800, 650, GetCamX());
	PrintText(600, 675, "Cam Pos(y) : ");
	PrintText(800, 675, GetCamY());	
	PrintText(600, 700, "Cam Pos(z) : ");
	PrintText(800, 700, GetCamZ());
}


void PlayState::PrintText(int x, int y, const std::string& s)
{
	//OPTIMISATION
	glDisable(GL_LIGHTING);
	glColor3f(0,0,0);

	glPushMatrix();
	glLoadIdentity();
	glMatrixMode(GL_PROJECTION);
	glPushMatrix ();
	glLoadIdentity();
	GLint viewport [4];
	glGetIntegerv (GL_VIEWPORT, viewport);
	gluOrtho2D (0,viewport[2], viewport[3], 0);

	glDepthFunc (GL_ALWAYS);

	//
	glRasterPos2f(x, y);
	for (unsigned int i = 0; i < s.size() ; ++i)
		glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_24, s[i]);
	glDepthFunc (GL_LESS);
	glPopMatrix ();
	glMatrixMode(GL_MODELVIEW);
	glPopMatrix ();

	glEnable(GL_LIGHTING);
	glColor3f(1, 1, 1);
}

std::string PlayState::GetPosX()
{
	std::ostringstream oss;
	oss << TheCar::Instance()->GetPos().GetX();
	std::string s = oss.str();
	return s;
}

std::string PlayState::GetPosY()
{

	std::ostringstream oss1;
	oss1 << TheCar::Instance()->GetPos().GetY();
	std::string s = oss1.str();	
	return s;

}
std::string PlayState::GetPosZ()
{

	std::ostringstream oss2;
	oss2 << TheCar::Instance()->GetPos().GetZ();
	std::string s = oss2.str();	
	return s;

}
std::string PlayState::GetVelX()
{
	std::ostringstream oss;
	oss << TheCar::Instance()->GetVel().GetX();
	std::string s = oss.str();
	return s;
}

std::string PlayState::GetVelY()
{

	std::ostringstream oss1;
	oss1 << TheCar::Instance()->GetVel().GetY();
	std::string s = oss1.str();	
	return s;

}
std::string PlayState::GetVelZ()
{

	std::ostringstream oss2;
	oss2 << TheCar::Instance()->GetVel().GetZ();
	std::string s = oss2.str();	
	return s;

}
std::string PlayState::GetCamX()
{
	std::ostringstream oss;
	oss << TheCamera::Instance()->GetPos().GetX();
	std::string s = oss.str();
	return s;
}

std::string PlayState::GetCamY()
{

	std::ostringstream oss1;
	oss1 << TheCamera::Instance()->GetPos().GetY();
	std::string s = oss1.str();	
	return s;

}
std::string PlayState::GetCamZ()
{

	std::ostringstream oss2;
	oss2 << TheCamera::Instance()->GetPos().GetZ();
	std::string s = oss2.str();	
	return s;

}